home *** CD-ROM | disk | FTP | other *** search
- /*
- * tclWinNotify.c --
- *
- * This file contains Windows-specific procedures for the notifier,
- * which is the lowest-level part of the Tcl event loop. This file
- * works together with ../generic/tclNotify.c.
- *
- * Copyright (c) 1995-1996 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * SCCS: @(#) tclWinNotify.c 1.8 96/02/29 09:19:08
- */
-
- #include "tclInt.h"
- #include "tclPort.h"
- #ifndef STk_CODE
- # include <winsock.h>
- #endif
-
- /*
- * The following variable is a backdoor for use by Tk. It is set when
- * Tk needs to process events on the Tcl event queue without reentering
- * the system event loop. Tk uses it to flush the Tcl event queue.
- */
-
- static int ignoreEvents = 0;
-
- /*
- *----------------------------------------------------------------------
- *
- * TclWinFlushEvents --
- *
- * This function is a special purpose hack to allow Tk to
- * process queued Window events during a recursive event loop
- * without looking for new events on the system event queue.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Services any pending Tcl events and calls idle handlers.
- *
- *----------------------------------------------------------------------
- */
-
- void
- TclWinFlushEvents()
- {
- ignoreEvents = 1;
- while (Tcl_DoOneEvent(TCL_DONT_WAIT|TCL_WINDOW_EVENTS|TCL_IDLE_EVENTS)) {
- }
- ignoreEvents = 0;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Tcl_WatchFile --
- *
- * Arrange for Tcl_DoOneEvent to include this file in the masks
- * for the next call to select. This procedure is invoked by
- * event sources, which are in turn invoked by Tcl_DoOneEvent
- * before it invokes select.
- *
- * Results:
- * None.
- *
- * Side effects:
- *
- * The notifier will generate a file event when the I/O channel
- * given by fd next becomes ready in the way indicated by mask.
- * If fd is already registered then the old mask will be replaced
- * with the new one. Once the event is sent, the notifier will
- * not send any more events about the fd until the next call to
- * Tcl_NotifyFile.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Tcl_WatchFile(file, mask)
- Tcl_File file; /* Opaque identifier for a stream. */
- int mask; /* OR'ed combination of TCL_READABLE,
- * TCL_WRITABLE, and TCL_EXCEPTION:
- * indicates conditions to wait for
- * in select. */
- {
- int type;
-
- (void) Tcl_GetFileInfo(file, &type);
-
- if (type == TCL_WIN_SOCKET) {
- #ifndef STk_CODE
- TclWinWatchSocket(file, mask);
- #endif
- } else if (type == TCL_WIN_FILE) {
- Tcl_Time timeout = { 0, 0 };
-
- /*
- * Files are always ready under Windows, so we just set a
- * 0 timeout.
- */
-
- Tcl_SetMaxBlockTime(&timeout);
- } else if (type == TCL_WIN_PIPE) {
- /*
- * We don't support waiting on pipes yet.
- */
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Tcl_FileReady --
- *
- * Indicates what conditions (readable, writable, etc.) were
- * present on a file the last time the notifier invoked select.
- * This procedure is typically invoked by event sources to see
- * if they should queue events.
- *
- * Results:
- * The return value is 0 if none of the conditions specified by mask
- * was true for fd the last time the system checked. If any of the
- * conditions were true, then the return value is a mask of those
- * that were true.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- int
- Tcl_FileReady(file, mask)
- Tcl_File file; /* File handle for a stream. */
- int mask; /* OR'ed combination of TCL_READABLE,
- * TCL_WRITABLE, and TCL_EXCEPTION:
- * indicates conditions caller cares about. */
- {
- int type;
-
- (void) Tcl_GetFileInfo(file, &type);
-
- if (type == TCL_WIN_SOCKET) {
- #ifndef STk_CODE
- return TclWinSocketReady(file, mask);
- #endif
- } else if (type == TCL_WIN_FILE) {
- /*
- * Under Windows, files are always ready, so we just return the
- * mask that was passed in.
- */
-
- return mask;
- }
- return 0;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Tcl_WaitForEvent --
- *
- * This procedure does the lowest level wait for events in a
- * platform-specific manner. It uses information provided by
- * previous calls to Tcl_WatchFile, plus the timePtr argument,
- * to determine what to wait for and how long to wait.
- *
- * Results:
- * The return value is normally TCL_OK. However, if there are
- * no events to wait for (e.g. no files and no timers) so that
- * the procedure would block forever, then it returns TCL_ERROR.
- *
- * Side effects:
- * May put the process to sleep for a while, depending on timePtr.
- * When this procedure returns, an event of interest to the application
- * has probably, but not necessarily, occurred.
- *
- *----------------------------------------------------------------------
- */
-
- int
- Tcl_WaitForEvent(timePtr)
- Tcl_Time *timePtr; /* Specifies the maximum amount of time
- * that this procedure should block before
- * returning. The time is given as an
- * interval, not an absolute wakeup time.
- * NULL means block forever. */
- {
- MSG msg;
- int foundEvent = 1;
-
- /*
- * If we are ignoring events from the system, just return immediately.
- */
-
- if (ignoreEvents) {
- return TCL_OK;
- }
-
- /*
- * Set up the asynchronous select handlers for any sockets we
- * are watching.
- */
- #ifndef STk_CODE
- TclWinNotifySocket();
- #endif
-
- /*
- * Look for an event, setting a timer so we don't block forever.
- */
-
- if (timePtr != NULL) {
- UINT ms;
- ms = timePtr->sec * 1000;
- ms += timePtr->usec / 1000;
-
- if (ms > 0) {
- UINT timerHandle = SetTimer(NULL, 0, ms, NULL);
- GetMessage(&msg, NULL, 0, 0);
- KillTimer(NULL, timerHandle);
- } else {
-
- /*
- * If the timeout is too small, we just poll.
- */
-
- foundEvent = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
- }
- } else {
- GetMessage(&msg, NULL, 0, 0);
- }
-
- /*
- * Dispatch the message, if we found one. If we are exiting, be
- * sure to inform Tcl so we can clean up properly.
- */
-
- if (foundEvent) {
- if (msg.message == WM_QUIT) {
- Tcl_Exit(0);
- }
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- return TCL_OK;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Tcl_Sleep --
- *
- * Delay execution for the specified number of milliseconds.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Time passes.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Tcl_Sleep(ms)
- int ms; /* Number of milliseconds to sleep. */
- {
- Sleep(ms);
- }
-